﻿using System;
using System.Collections;
using System.IO;
using System.Xml.Linq;

using Caliburn.Micro;


namespace DailyFx.UI
{
	public class ConfigurationPersistentManager : IConfigurationPersistentManager
	{
		internal const string CONFIG_OBJECT = "ConfigurationObject";
		internal const string CONFIG_PROPERTY = "Property";
		internal const string CONFIG_TYPE = "Type";
		internal const string CONFIG_NAME = "Name";


		private String m_Path = null ;
		private Version mVersion = new Version(0, 1, 0, 0);
		private SortedList m_Configs = new SortedList();

		//
		public static ILog mLog = LogManager.GetLog( typeof( ConfigurationPersistentManager));


		public ConfigurationPersistentManager ( string configPath)
		{
			string appDir = Environment.CurrentDirectory;
			this.m_Path = System.IO.Path.Combine( appDir, configPath);

			this.Load();
		}



		public string Path
		{
			get { return m_Path; }
		}


		protected SortedList Configs
		{
			get
			{
				return this.m_Configs;
			}
		}


		public void Load ()
		{
			this.Configs.Clear();
			try
			{
				if (File.Exists( this.Path) )
				{
					XElement root = XElement.Load( this.Path );
					_Loadimpl (root);
				}
			}
			catch (Exception e)
			{
				mLog.Error(e);
			}
		}

		public void Save()
		{
			try
			{
				Directory.CreateDirectory(this.Path);
				XElement element = new XElement( CONFIG_OBJECT);
				_SaveImpl( element);
				
				XDocument document = new XDocument( element);
				document.Save( this.Path);
			}
			catch (Exception e)
			{
				mLog.Error(e);
			}
		}

		public IConfiguration this [ string name]
		{
			get
			{
				if ( this.m_Configs.Contains(name))
				{
					return (IConfiguration)this.m_Configs[ name];
				}
				
				Configuration c = new Configuration();
				this.m_Configs[ name] = c;
				
				return c;
			}
			set
			{
				if ( value == null)
				{
					if (this.m_Configs.Contains(name) )
					{
						this.m_Configs.Remove( name);
					}
				}
				else
				{
					this.m_Configs[ name] = value;
				}
			}
		}



		protected void _Loadimpl ( XElement element)
		{
			if (element != null)
			{
				foreach (var e in element.Elements())
				{
					_Loadimpl ( e);
				}
				string name = element.Attribute(XName.Get(CONFIG_NAME)).Value;
				Configuration c = (Configuration)this[name];
				if (c != null)
				{
					c.Load ( element) ;
				}
			}
		}

		protected void _SaveImpl ( XElement element)
		{
			if ( element != null)
			{
				string[] configKeys = new string[ this.m_Configs.Count];
				this.m_Configs.Keys.CopyTo(configKeys, 0);

				foreach ( string key in configKeys)
				{
					var e = new XElement( CONFIG_OBJECT);
					e.SetAttributeValue( CONFIG_NAME, key );

					( (Configuration)this.m_Configs[key]).Save( e);
					//
					element.Add( e);
				}
			}
		}

	}
}
